package com.polaris.live.widget.gift

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.view.animation.LinearInterpolator
import android.view.animation.TranslateAnimation
import androidx.constraintlayout.widget.ConstraintLayout
import com.blankj.utilcode.util.ColorUtils
import com.blankj.utilcode.util.SpanUtils
import com.blankj.utilcode.util.StringUtils
import com.bumptech.glide.Glide
import com.polaris.live.R
import com.polaris.live.common.ext.autoDp
import com.polaris.live.common.ext.setOnSingleClickListener
import com.polaris.live.common.manager.CoroutineScopeManager
import com.polaris.live.common.util.AppCodeUtils
import com.polaris.live.databinding.LayoutLiveGiftBinding
import com.polaris.live.im.sfs.bean.live.ext.UserBasicVo
import com.polaris.live.im.sfs.bean.live.payload.InviteGiftPayloadBean
import com.polaris.live.interface_bag.AnimationListenerAdapter
import com.polaris.live.resp.bean.GiftNeedBean
import com.polaris.live.translation.R.string
import com.polaris.live.ui.live.proxy.gift.GiftAnimationProxy
import com.polaris.live.utils.image.ImageUtils
import com.polaris.live.widget.avatar.FrameImageUtils
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 * LiveGiftItemView
 *
 * @author Created by 半仙 on 2023/11/13/013 11:19
 */
class LiveGiftItemView(context: Context, attrs: AttributeSet? = null) :
    ConstraintLayout(context, attrs) {

    private var mScaleAnimator: ObjectAnimator? = null
    private var mAnimator: ValueAnimator? = null

    private var outAnim: TranslateAnimation? = null
    private var inAnim: TranslateAnimation? = null

    val mBinding = LayoutLiveGiftBinding.inflate(LayoutInflater.from(context), this, true)

    private var mGiftJob: Job? = null

    private var key: String? = null

    /**
     * 开始走关闭动画
     */
    var startEndAnm: Boolean = false

    //展示的数据
    private var userBasicVo: UserBasicVo? = null
    private var payload: InviteGiftPayloadBean? = null

    //礼物动画数量需要的数据
    private var giftNeedBean: GiftNeedBean? = null

    //礼物动画代理类
    private var giftAnimationProxy: GiftAnimationProxy? = null

    //结束回调
    private var onGiftAnimationEnd: ((key: String) -> Unit)? = null
    fun setOnGiftAnimationEnd(click: (key: String) -> Unit) {
        onGiftAnimationEnd = click
    }

    //头像点击回调
    private var onHeadOnClickListener: ((otherId: Long) -> Unit)? = null
    fun setOnHeadOnClickListener(click: (otherId: Long) -> Unit) {
        onHeadOnClickListener = click
    }

    //数字跳动更新
    private var onNumListener: (() -> Unit)? = null
    fun setOnNumListener(back: () -> Unit) {
        onNumListener = back
    }

    init {

        if (AppCodeUtils.isAR()) {
            outAnim =
                AnimationUtils.loadAnimation(
                    context,
                    R.anim.ar_gift_out
                ) as TranslateAnimation // 礼物退出时动画
            inAnim =
                AnimationUtils.loadAnimation(
                    context,
                    R.anim.ar_gift_in
                ) as TranslateAnimation // 礼物进入时动画
        } else {
            outAnim =
                AnimationUtils.loadAnimation(
                    context,
                    R.anim.gift_out
                ) as TranslateAnimation // 礼物退出时动画
            inAnim =

                AnimationUtils.loadAnimation(
                    context,
                    R.anim.gift_in
                ) as TranslateAnimation // 礼物进入时动画
        }
    }

    /**
     * 获取谁送的
     */
    fun getSendUserId(): Long? {
        return userBasicVo?.userId
    }

    fun setData(
        userBasicVo: UserBasicVo,
        payload: InviteGiftPayloadBean,
        nickName: String,
        key: String,
        isCache: Boolean,
        giftNeedBean: GiftNeedBean,
        giftAnimationProxy: GiftAnimationProxy,
    ) {
        this.key = key
        this.payload = payload
        this.userBasicVo = userBasicVo
        this.giftNeedBean = giftNeedBean
        this.giftAnimationProxy = giftAnimationProxy
        mBinding.apply {
            payload.giftFloat?.let {
                Glide.with(bgImg).load(ImageUtils.imgPath(it))
                    .into(bgImg)
            }
            layoutGiftUserHead.setImageUrl(userBasicVo.avatar, userBasicVo.userId)
            avFv.setFrameImage(FrameImageUtils.urlToFrameImageBean(userBasicVo.avatarFrame))
            layoutGiftUserName.text = userBasicVo.nickname
            layoutGiftUserName.setNicknameColor(
                userBasicVo.nicknameColor,
                R.color.white
            )

            Glide.with(context).load(ImageUtils.imgPath(payload.gift.pic))
                .into(layoutGiftImg)

            layoutIvFrame.setImageResource(0)
            val giftBean = payload.gift.payloadBean
            val layout = layoutGiftImg.layoutParams as LayoutParams
            if (!giftBean?.frame.isNullOrEmpty()) {
                Glide.with(context).load(ImageUtils.imgPath(giftBean?.frame))
                    .into(layoutIvFrame)
                layout.width = 25.autoDp
                layout.height = 34.autoDp
            } else {
                layout.width = 48.autoDp
                layout.height = 48.autoDp
            }
            layoutGiftImg.layoutParams = layout

            if (isCache) {
                layoutGiftCount.text = "×${giftNeedBean.nowNum}"
            } else {
                layoutGiftCount.text = "×1"
            }

            val span = payload.nickname?.let {
                SpanUtils.with(layoutGiftGive)
                    .append("${StringUtils.getString(string.give)} ")
                    .append(it)
                    .setForegroundColor(ColorUtils.getColor(R.color.color_fff1b1))
                    .create()
            }
            layoutGiftGive.text = span

            layoutGiftUserHead.setOnSingleClickListener {
                onHeadOnClickListener?.invoke(userBasicVo.userId)
            }
        }
    }

    //礼物动画分发展示
    fun startAnimation() {
        mBinding.root.startAnimation(inAnim)

        inAnim?.setAnimationListener(object : Animation.AnimationListener {
            override fun onAnimationStart(animation: Animation) {}
            override fun onAnimationRepeat(animation: Animation) {}
            override fun onAnimationEnd(animation: Animation) {
                animationDispatch()
            }
        })
    }

    //数据变更
    fun dataChange(payload: InviteGiftPayloadBean) {
        val endNum = giftNeedBean?.endNum
        if (endNum != null) {
            giftNeedBean?.endNum = endNum + payload.giftCount
        }
    }

    //动画分发
    fun animationDispatch() {
        //开始动画
        if (giftNeedBean?.isThanTen == true) {
            giftValues()
        } else {
            scaleAnimation()
        }
    }

    //礼物滚动动画
    private fun giftValues() {
        val giftNeedBean = giftNeedBean
        if (giftNeedBean != null) {
            val startNum = giftNeedBean.nowNum
            val endNum = giftNeedBean.endNum

            //动画初始化
            mAnimator = ValueAnimator.ofInt(startNum, endNum - GiftAnimationProxy.LASTNUM)
            mAnimator?.interpolator = LinearInterpolator()
            // 动画持续时间，单位为毫秒
            mAnimator?.duration = getDuration(endNum, startNum)

            mAnimator?.addUpdateListener { animation ->
                val value = animation.animatedValue as Int
                // 在此处更新数字视图的显示值，例如将 value 设置给 TextView
                mBinding.layoutGiftCount.text = "×$value "
                //实时更新滚动的数量
                giftNeedBean.nowNum = value
                //判断当前数量 到 到最后 10
                if (giftNeedBean.nowNum == endNum - GiftAnimationProxy.LASTNUM) {
                    //小于10了停止滚动动画
                    scaleAnimation()
                }
            }
            mAnimator?.start()
        }
    }

    //礼物变大变小动画
    private fun scaleAnimation() {
        val giftNeedBean = giftNeedBean ?: return

        //如果发现数量差距不是10则回去继续执行滚动动画
        if (giftNeedBean.endNum - giftNeedBean.nowNum > GiftAnimationProxy.LASTNUM) {
            giftValues()
            return
        }

        mScaleAnimator = ObjectAnimator.ofPropertyValuesHolder(
            mBinding.layoutGiftCount,
            PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f, 1.0f),
            PropertyValuesHolder.ofFloat("scaleY", 1.0f, 1.5f, 1.0f)
        )
        mScaleAnimator?.interpolator = LinearInterpolator()
        mScaleAnimator?.duration = GiftAnimationProxy.BIGTOSMALL
        mScaleAnimator?.addListener(object : AnimatorListenerAdapter() {

            override fun onAnimationEnd(animation: Animator) {
                super.onAnimationEnd(animation)
                onNumListener?.invoke()
                if (giftNeedBean.nowNum != giftNeedBean.endNum) {
                    //结束后更新数量
                    giftNeedBean.nowNum = giftNeedBean.nowNum + 1
                }
                val nowNum = giftNeedBean.nowNum
                val endNum = giftNeedBean.endNum
                mBinding.layoutGiftCount.text = "×$nowNum "
                //判断当前展示的数量是不是总数  并且   判断当前数量与总数的差  只有小于等于10的才可以继续跳动
                if (endNum - nowNum < GiftAnimationProxy.LASTNUM && nowNum < endNum) {
                    mBinding.root.post {
                        mScaleAnimator?.start()
                    }
                    return
                }

                if (endNum - nowNum > GiftAnimationProxy.LASTNUM) {
                    giftValues()
                    return
                }
                // 判断当前等待队列里有没有礼物  有就展示1秒 如果没有3秒
                val time = giftAnimationProxy?.getEndTime() ?: REMOVE_VIEW_LONG
                startEnd(time) {
                    key?.let { it1 -> onGiftAnimationEnd?.invoke(it1) }
                }
            }
        })
        mScaleAnimator?.start()
    }

    fun startEnd(timeMs: Long, onAnimationEnd: ((key: String) -> Unit)) {
        mGiftJob = CoroutineScopeManager.ioScope.launch {
            delay(timeMs)
            startEndAnm = true
            withContext(CoroutineScopeManager.mainDispatcher) {
                startAnimation(outAnim)
                outAnim?.setAnimationListener(object : AnimationListenerAdapter() {
                    override fun onAnimationEnd(animation: Animation) {
                        visibility = View.GONE
                        key?.let { onAnimationEnd.invoke(it) }
                    }
                })
            }
        }
    }

    fun endAnimation() {
        mGiftJob?.cancel()
        mGiftJob = null
    }

    //时间逻辑
    private fun getDuration(endNum: Int, startNum: Int): Long {
        val remainderNum = endNum - startNum
        val duration = if (remainderNum > HIGH_TIME_NUMBER) {
            (TIME_STEP * remainderNum).toLong()
        } else {
            (30 * (HIGH_TIME_NUMBER - remainderNum) / HIGH_TIME_NUMBER * remainderNum).toLong()
        }
        return if (duration > MAX_TIME) MAX_TIME else duration
    }

    companion object {

        const val LASTNUM = 10                  //最后的几个数字放大所有
        const val BIGTOSMALL = 500L             //数字放大
        const val TIME_STEP = 5
        const val HIGH_TIME_NUMBER = 250
        const val REMOVE_VIEW_LONG = 3000L      //移除延迟移除动画 3秒
        const val REMOVE_VIEW_SHORT = 1000L     //移除延迟移除动画 1秒
        const val MAX_TIME = 3500L              //最大时长3500
    }

    fun jobIsActive() = mGiftJob?.isActive

    fun jobCancel() {
        if (jobIsActive() == true) {
            mGiftJob?.cancel()
        }
    }
}